//---------------------------------------------------------------------------

#include "MyUtility.h"
#ifdef MY_BORLAND
#pragma package(smart_init)
#include <vcl.h>
#pragma hdrstop

//---------------------------------------------------------------------------
static inline void ValidCtrCheck(MyUtility *)
{
	new MyUtility();
}
#endif
//---------------------------------------------------------------------------
MyUtility::MyUtility(void)
{
	FUtilityVersion = UTILITY_VERSION;
	FDebugLevel = NO_DEBUG;
//	MemoryPool=HeapCreate(HEAP_NO_SERIALIZE,8192,4096*8);
	InternalChar =NULL;
	InternalBuffer=NULL;
	InternalWChar=NULL;
#ifdef MY_BORLAND	
	OnDebugMsg = DummyDebugMsg;
	OnWarningEvt = DummyWarnEvt;
	OnErrorEvt = DummyErrEvt;
#endif
	DebugMsgCount = 0;
}
//---------------------------------------------------------------------------
int MyUtility::GetUtilityVersion()
{
	return FUtilityVersion;
}
//---------------------------------------------------------------------------
void MyUtility::SetDebugLevel(int val)
{
	FDebugLevel = val;
}
//---------------------------------------------------------------------------
int MyUtility::GetDebugLevel()
{
	return FDebugLevel;
}
//---------------------------------------------------------------------------
char* MyUtility::DumpRow(void *Buffer, int BufferLen)
{
	char *Tmp = InternalDumpRow(Buffer,BufferLen);
	return Tmp;
}
//---------------------------------------------------------------------------
char* MyUtility::DumpBuffer(void *Buffer, int BufferLen, char *Preamble, bool ShowBytes)
{
	unsigned char *In = (unsigned char*)Buffer;
	int NumLines = 1+(BufferLen/16);
	int a;
	int Index;
	char *Spacer = "    ";
	int TotalSize;
	if(Preamble != NULL)
	   TotalSize = NumLines * (68 + strlen(Preamble) + strlen(Spacer)) + 1;
	else
    	TotalSize = NumLines * (68 + strlen(Spacer)) + 1;
	char *Out = (char*)malloc(TotalSize);
	memset(Out,0,TotalSize);
	int LineLen;
	a = 0;
	Index = 0;
	while(a < NumLines)
	{
		if(a+1 == NumLines)
			LineLen = BufferLen%0x10;
		else
			LineLen = 0x10;
		if(Preamble != NULL)
    		sprintf(Out+strlen(Out),"%s%s",Preamble,InternalDumpRow(In + (0x10*a),LineLen));
        else
    		sprintf(Out+strlen(Out),"%s",InternalDumpRow(In + (0x10*a),LineLen));
		if(LineLen != 0x10)
		{
			int b;
			for(b=LineLen;b<0x10;b++)
				sprintf(Out+strlen(Out),"   ");
        }
		if(ShowBytes)
			sprintf(Out+strlen(Out),"%s%s",Spacer,DumpByte(In + (0x10*a),LineLen));
		Index+=LineLen;
		if(Index>=BufferLen)
			a++;
		if(a+1 < NumLines)
			//sprintf(Out+strlen(Out),"\r\n");
			sprintf(Out+strlen(Out),"%s",MY_NEWLINE);
		a++;
	}
	return Out;
}
//---------------------------------------------------------------------------
void *MyUtility::TextToBuffer(char *Src, int *Len)
{
	unsigned char *In =(unsigned char*)Src;
	int SrcLen = strlen(Src);
	int DataLen;
	int a=0;
	InternalChar = (char*)malloc(SrcLen + 1);
	DataLen = 0;
	while(a<SrcLen)
	{
		if(isValidByte(In[a]))
		{
			InternalChar[DataLen] = Src[a];
			DataLen++;
		}
		a++;
	}
	if(DataLen % 2)
	{
		InternalChar[DataLen+1] = '0';
		DataLen++;
	}
	a=0;
	InternalBuffer = (unsigned char*)malloc(DataLen/2);
	*Len = DataLen/2;
	while(a<DataLen)
	{
		InternalBuffer[a/2]=GetByteValue(InternalChar[a+1])+(0x10 * GetByteValue(InternalChar[a]));
		a+=2;
	}
	return InternalBuffer;
}
//---------------------------------------------------------------------------
bool MyUtility::isValidByte(unsigned char Value)
{
	if(Value>='0' && Value <='9')
		return true;
	else
	{
		if(Value>='A' && Value<='F')
			return true;
		else
		{
			if(Value >='a' && Value <='f')
				return true;
        }
    }
	return false;
}
//---------------------------------------------------------------------------
int MyUtility::GetByteValue(char Value)
{
	int Out = -1;
	if(Value>='0' && Value<='9')
		return Value-'0';
	else
	{
		if(Value>='A' && Value<='F')
			return 10+Value-'A';
		else
		{
			if(Value>='a' && Value<='f')
				return 10+Value-'a';
		}
	}
	return Out;
}
//---------------------------------------------------------------------------
char* MyUtility::GetNow(void)
{
    char Txt[0x30];
	SYSTEMTIME Now;
	GetLocalTime(&Now);
	//InternalChar = (char*)malloc(0x100);
	//memset(InternalChar,0,0x100);
	memset(Txt,0,0x30);
//	sprintf(InternalChar,"%02d/%02d/%2d-%02d:%02d:%02d.%03d",Now.wDay,Now.wMonth,
	sprintf(Txt,"%02d/%02d/%2d-%02d:%02d:%02d.%03d",Now.wDay,Now.wMonth,
				Now.wYear%100,Now.wHour,Now.wMinute,Now.wSecond,Now.wMilliseconds);
//	return DuplicateString(InternalChar);
	return DuplicateString(Txt);
}
//---------------------------------------------------------------------------
char* MyUtility::FormattedNow(char *PreNow, char *PostNow)
{
    int PreLen, PostLen;
    if(PreNow != NULL)
        PreLen = strlen(PreNow);
    else
        PreLen = 0;
    if(PostNow != NULL)
        PostLen = strlen(PostNow);
    else
        PostLen = 0;        
	char *Tmp = GetNow();
	char *Out = (char*)malloc(1+strlen(Tmp)+PreLen+PostLen);
	memset(Out,0,1+strlen(Tmp)+PreLen+PostLen);
    if(PreLen != 0)
        sprintf(Out,"%s",PreNow);
    sprintf(Out+strlen(Out),"%s",Tmp);
    if(PostLen != 0)
        sprintf(Out+strlen(Out),"%s",PostNow);        
/*	memcpy(Out,PreNow,PreLen);
	memcpy(Out+strlen(PreNow),Tmp,strlen(Tmp));
	memcpy(Out+strlen(PreNow)+strlen(Tmp),PostNow,PostLen);*/
	return Out;
}
//---------------------------------------------------------------------------
DWORD MyUtility::LogToFile(char *FileName, char *Msg)
{
	FILE  *out;
	out = fopen(FileName,"a");
	int MsgLen=strlen(Msg);
	char *Temp = (char*)malloc(MsgLen+5);
	memcpy(Temp,Msg,MsgLen);
	if(Temp[MsgLen-1] == '\n' || Temp[MsgLen-1] == '\r')
	{
        if(Temp[MsgLen-2] == '\n' || Temp[MsgLen-2] == '\r')
            MsgLen -= 2;
        else
            MsgLen --;
    }
    sprintf(Temp+MsgLen,"%s",MY_NEWLINE);
    MsgLen +=strlen(MY_NEWLINE);
/*	if(Temp[MsgLen-1]!='\n')
	{
		if(Temp[MsgLen-2]!='\r')
		{
			Temp[MsgLen]='\r';
			Temp[MsgLen+1]='\n';
			MsgLen+=2;
		}
		else
		{
            Temp[MsgLen-1]='\n';
        }
    }
	else
	{
		if(Temp[MsgLen-1]=='\r')
		{
			Temp[MsgLen]='\n';
			MsgLen++;
		}
		else
		{
			//memcpy(Temp+MsgLen,"\r\n",2);
			sprintf(Temp+MsgLen,"%s",MY_NEWLINE);
			MsgLen+=2;
		}
	}*/
	fwrite(Temp,MsgLen,1,out);
	fclose(out);
	return 0;
}
//---------------------------------------------------------------------------
char* MyUtility::wchar_to_char(wchar_t* Input)
{
	if(Input != NULL)
	{
		char *Tmp = (char*)malloc(wcslen(Input)+0x10);
		memset(Tmp,0,wcslen(Input)+0x10);
		wcstombs(Tmp,Input,wcslen(Input)+0x10);
		return Tmp;
	}
	return NULL;
}
//---------------------------------------------------------------------------
wchar_t* MyUtility::char_to_wchar(char* Input)
{
	wchar_t *Tmp = (wchar_t*)malloc(strlen(Input)*2 + 4);
	wmemset(Tmp,0,strlen(Input)+1);
	mbstowcs(Tmp,Input,strlen(Input));
	return Tmp;
}
//---------------------------------------------------------------------------
void MyUtility::DummyDebugMsg(DWORD Level, char *Msg)
{
	if(Level<=(DWORD)FDebugLevel)
	{
		char *Temp = (char*)malloc(strlen(Msg)+1);
		memset(Temp, 0, strlen(Msg)+1);
		memcpy(Temp,Msg,strlen(Msg));
		DebugMsgCount++;
		if(DebugMsgCount>MAX_DEBUG_MESSAGE)
		{
			DebugMsgCount=MAX_DEBUG_MESSAGE;
			DebugMessage.pop_front();
		}
		DebugMessage.push_back(Temp);
	}
}
//---------------------------------------------------------------------------
void MyUtility::DummyWarnEvt(DWORD Code, DWORD SubCode, void *Add_Data)
{
	//Do nothing..
}
//---------------------------------------------------------------------------
void MyUtility::DummyErrEvt(DWORD Code, DWORD SubCode, void*Add_Data)
{
	//Do nothing..
}
//---------------------------------------------------------------------------
char* MyUtility::GetErrorDesc(DWORD Error)
{
	LPTSTR  Msg;
	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
						0,Error,0,(LPTSTR)&Msg,0,0);
	char *Tmp;
#ifdef CHAR_MODE
	Tmp = Msg;
#elseif
	Tmp = wchar_to_char(Msg);
#endif
	char *Tmp2 = (char*)malloc(strlen(Tmp)+1);
	memset(Tmp2,0,strlen(Tmp)+1);
	memcpy(Tmp2,Tmp,strlen(Tmp));
	InternalChar = (char*)malloc(strlen(Tmp2)+1);
	memset(InternalChar,0,strlen(Tmp2)+1);
	memcpy(InternalChar,Tmp2,strlen(Tmp2));
	int a = strlen(InternalChar);
	if(InternalChar[a-1]=='\n' || InternalChar[a-1]=='\r')
		InternalChar[a-1]=0;
	if(InternalChar[a-2]=='\r')
		InternalChar[a-2]=0;
	return InternalChar;
}
//---------------------------------------------------------------------------
void MyUtility::FormatDebugMsg(DWORD Level,char *Format,...)
{
	char Mess[0x400];
	memset(Mess,0,0x400);
    va_list args;
    va_start (args, Format);
    vsprintf (Mess,Format, args);
    va_end (args);
    OnDebugMsg(Level,Mess);
}
//---------------------------------------------------------------------------
void MyUtility::FormatLogToFile(char *File,char *Format,...)
{
	char Mess[0x400];
	memset(Mess,0,0x400);
  va_list args;
  va_start (args, Format);
  vsprintf (Mess,Format, args);
  va_end (args);
  LogToFile(File,Mess);
}
//---------------------------------------------------------------------------
char *MyUtility::GenerateString(char *Format,...)
{
	char Mess[0x400];
	memset(Mess,0,0x400);
    va_list args;
    va_start (args, Format);
    vsprintf (Mess,Format, args);
    va_end (args);
	return DuplicateString(Mess);
}
//---------------------------------------------------------------------------
char* MyUtility::DumpByte(void *Buff, int Size)
{
	char *Out=(char*)malloc(Size+0x10);
	MyUCHAR *In = (MyUCHAR*)Buff;
	memset(Out,0,Size+1);
	int a;
	for(a=0;a<Size;a++)
	{
		if(In[a]>=0x20)
			sprintf(Out+strlen(Out),"%c",In[a]);
		else
			sprintf(Out+strlen(Out),".");
	}
	return Out;
}
//---------------------------------------------------------------------------
char* MyUtility::InternalDumpRow(void *Buff, int Size)
{
	char *Out=(char*)malloc(Size*3+1);
	memset(Out,0,Size*3+1);
	MyUCHAR *In = (MyUCHAR*)Buff;
	int a;
	sprintf(Out,"%02X",In[0]);
	for(a=1;a<Size;a++)
		sprintf(Out+strlen(Out)," %02X",In[a]);
	return Out;	
}
//---------------------------------------------------------------------------
int MyUtility::My_atoi(char *Val)
{
	int Out = 0;
	char *Test = strstr(Val,"0x");
	if(Test!=NULL)
		sscanf(Test,"0x%x",&Out);
	else
		sscanf(Val,"%d",&Out);
	return Out;
}
//---------------------------------------------------------------------------
char *MyUtility::CurrentDirectory()
{
	char *Out = (char*)malloc(0x400);
	memset(Out,0,0x400);
	char *Out2;
	DWORD Size =0x400;
#ifdef UNICODE	
		wchar_t TmpDirW[0x400];	
		//GetCurrentDirectory(TmpDirW);
		GetCurrentDirectory(0x400,TmpDirW);
		Out2 = wchar_to_char(TmpDirW);
		memcpy(Out, Out2, strlen(Out2));
#else
		GetCurrentDirectory(0x400,Out);
#endif
	return DuplicateString(Out);
}
//---------------------------------------------------------------------------
char *MyUtility::GetCurrentAppDirectory()
{
	char *Out = (char*)malloc(0x400);
	memset(Out,0,0x400);
	char *Out2;
	DWORD Size =0x400;
#ifdef UNICODE	
		wchar_t TmpDirW[0x400];	
		GetModuleFileName(NULL,TmpDirW,0x400);
		Out2 = wchar_to_char(TmpDirW);
		memcpy(Out, Out2, strlen(Out2));
#else
		GetModuleFileName(NULL,Out,0x400);
#endif
	return ExtractDirFromFile(Out);
}
//---------------------------------------------------------------------------
char *MyUtility::MyMoveFile(char *SrcFile, char *DirDest)
{

#ifdef UNICODE 
		wchar_t DirW[0x400];
		wchar_t *FW=char_to_wchar(DirDest);
		wchar_t *TmpW;
		GetFullPathName(FW,0x400,DirW,&TmpW);
		if(TmpW != NULL)
		{
			if(MoveFile(char_to_wchar(SrcFile),char_to_wchar(DirDest)))
				return DuplicateString(DirDest);	
		}
		else
		{
			FW=char_to_wchar(SrcFile);
			GetFullPathName(FW,0x400,DirW,&TmpW);
			wchar_t TempNameW[0x400];
			memset(TempNameW,0x0,sizeof(TempNameW));
			swprintf(TempNameW,L"%s",char_to_wchar(DirDest));
			swprintf(TempNameW+wcslen(TempNameW),L"%s",TmpW);
			if(MoveFile(char_to_wchar(SrcFile),TempNameW))
			{
				return DuplicateString(wchar_to_char(TempNameW));	
			}
		}
#else
		char TempName[0x400];
		char *TmpName;
		memset(TempName,0,0x400);		
		GetFullPathName(DirDest,0x400,TempName,&TmpName);
		if(TmpName != NULL)
		{
			if(MoveFile(SrcFile,DirDest))
			{
				return DuplicateString(DirDest);
			}
		}
		else
		{
			GetFullPathName(SrcFile,0x400,TempName,&TmpName);
			char OutName[0x400];
			memset(OutName,0,0x400);
			sprintf(OutName,"%s",DirDest);
			sprintf(OutName+strlen(OutName),"%s",TmpName);
			if(MoveFile(SrcFile,OutName))
			{
				return DuplicateString(OutName);
			}
		}
#endif			
		return NULL;
}
//---------------------------------------------------------------------------
char *MyUtility::DuplicateString(char *Src)
{
	char *Out = NULL;
	if(Src!=NULL)
	{
		Out = (char*)malloc(strlen(Src)+1);
		memset(Out,0,strlen(Src)+1);
		memcpy(Out,Src,strlen(Src));
	}
	return Out;
}
//---------------------------------------------------------------------------
char *MyUtility::ExtractDirFromFile(char *FileName)
{
	if(FileName != NULL)
	{
		char *Out = (char*)malloc(strlen(FileName));
		memset(Out,0,strlen(FileName));
		int BuffLen = 0x400;
		char *Dir,*FName;
#ifdef UNICODE
		wchar_t *lpBuffer = (wchar_t*)malloc(BuffLen * sizeof(wchar_t));
		wchar_t *FilePart;
		GetFullPathName(char_to_wchar(FileName),BuffLen,lpBuffer,&FilePart);
		Dir = wchar_to_char(lpBuffer);
		FName = wchar_to_char(FilePart);
#else
		char *Tmp = (char*)malloc(BuffLen);
		GetFullPathName(FileName,BuffLen,Tmp,&FName);
		Dir = Tmp;
#endif		
		memcpy(Out,Dir,strlen(Dir)-strlen(FName));
		return DuplicateString(Out);
	}
	return NULL;
}
//---------------------------------------------------------------------------
#ifndef MY_BORLAND
void MyUtility::OnDebugMsg(DWORD Level, char *Msg)
{
	DummyDebugMsg(Level, Msg);	
}
void MyUtility::OnWarningEvt(DWORD Code, DWORD SubCode, void*Add_Data)
{
	DummyWarnEvt(Code,SubCode,Add_Data);	
}
void MyUtility::OnErrorEvt(DWORD Code, DWORD SubCode, void*Add_Data)
{
	DummyErrEvt(Code,SubCode,Add_Data);	
}
#endif
//---------------------------------------------------------------------------
